/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package cz.muni.fi.pb138.jprvyd.gui;

import cz.muni.fi.pb138.jprvyd.gui.list.PaymentsList;
import cz.muni.fi.pb138.jprvyd.gui.list.ContactList;
import cz.muni.fi.pb138.jprvyd.gui.form.ContactForm;
import cz.muni.fi.pb138.jprvyd.gui.form.InvoiceForm;
import cz.muni.fi.pb138.jprvyd.gui.model.Main_TableModel;
import cz.muni.fi.pb138.jprvyd.*;
import cz.muni.fi.pb138.jprvyd.gui.form.TaxReturnForm;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import javax.swing.JOptionPane;
import javax.swing.SwingWorker;

/**
 *
 * @author Jan
 */
public class Main extends javax.swing.JFrame {

    private InvoiceManager invoiceManager;
    private SwingWorker swingWorker;
    private List<Invoice> invoices;
    private int rowIndex;
    public final int REMOVE = 0;
    public final int ADD = 1;
    public final int EDIT = 2;
    private final int NONE = 0;
    private final int NUMBER = 1;
    private final int VAR_SYMBOL = 2;
    private final int DATE = 3;
    private final int END_DATE = 4;
    private final int CONTACT = 5;
    private PaymentMethod paymentMethod;
    private Contact contact;

    /**
     * Creates new form InvoiceForm
     */
    public Main() {
        invoiceManager = new InvoiceManagerImpl();
        invoices = invoiceManager.getAllInvoices();
        rowIndex = -1;
        initComponents();
    }

    private class editSwingWorker extends SwingWorker<Integer, Void> {

        Main frame;
        Integer invoiceNumber;
        InvoiceManager invoiceManager;

        public editSwingWorker(Main frame, Integer invoiceNumber, InvoiceManager invoiceManager) {

            this.frame = frame;
            this.invoiceNumber = invoiceNumber;
            this.invoiceManager = invoiceManager;
        }

        @Override
        protected Integer doInBackground() throws Exception {
            Invoice invoice = invoiceManager.getInvoiceByNumber(invoiceNumber);
            InvoiceForm invoiceForm = new InvoiceForm(frame, invoice);
            invoiceForm.setVisible(true);
            return 0;
        }

        @Override
        protected void done() {
            swingWorker = null;
        }
    }

    private class deleteSwingWorker extends SwingWorker<Integer, Void> {

        InvoiceManager invoiceManager;

        public deleteSwingWorker(InvoiceManager invoiceManager) {
            this.invoiceManager = invoiceManager;
        }

        @Override
        protected Integer doInBackground() throws Exception {
            rowIndex = tableInvoices.getSelectedRow();
            Main_TableModel model = (Main_TableModel) tableInvoices.getModel();
            Integer invoiceNumber = (Integer) model.getValueAt(rowIndex, 0);
            Invoice invoice = invoiceManager.getInvoiceByNumber(invoiceNumber);
            invoiceManager.removeInvoice(invoice.getId());
            refreshInvoices(invoices.get(rowIndex), REMOVE);
            return 0;
        }

        @Override
        protected void done() {
            swingWorker = null;
        }
    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        jScrollPane1 = new javax.swing.JScrollPane();
        tableInvoices = new javax.swing.JTable();
        buttonNewInvoice = new javax.swing.JButton();
        buttonNewContact = new javax.swing.JButton();
        buttonDeleteInvoice = new javax.swing.JButton();
        buttonEditInvoice = new javax.swing.JButton();
        labelFilter = new javax.swing.JLabel();
        comboBoxFilter = new javax.swing.JComboBox();
        textFieldFilter = new javax.swing.JTextField();
        buttonBrowse = new javax.swing.JButton();
        jSeparator1 = new javax.swing.JSeparator();
        buttonManagePayments = new javax.swing.JButton();
        buttonPrepareTaxReturn = new javax.swing.JButton();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setTitle("JPrVyd - World's greates tool for handling invoices");

        tableInvoices.setModel(new Main_TableModel(invoices));
        tableInvoices.getTableHeader().setReorderingAllowed(false);
        tableInvoices.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                tableInvoicesMouseClicked(evt);
            }
        });
        jScrollPane1.setViewportView(tableInvoices);

        buttonNewInvoice.setText("New invoice");
        buttonNewInvoice.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                buttonNewInvoiceActionPerformed(evt);
            }
        });

        buttonNewContact.setText("New contact");
        buttonNewContact.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                buttonNewContactActionPerformed(evt);
            }
        });

        buttonDeleteInvoice.setText("Delete invoice");
        buttonDeleteInvoice.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                buttonDeleteInvoiceActionPerformed(evt);
            }
        });

        buttonEditInvoice.setText("Edit invoice");
        buttonEditInvoice.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                buttonEditInvoiceActionPerformed(evt);
            }
        });

        labelFilter.setText("Filter:");

        comboBoxFilter.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "None", "Number", "Variable symbol", "Date", "End date", "Contact"}));
        comboBoxFilter.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                comboBoxFilterActionPerformed(evt);
            }
        });

        textFieldFilter.setEnabled(false);
        textFieldFilter.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                textFieldFilterMouseClicked(evt);
            }
        });

        buttonBrowse.setText("Filter");
        buttonBrowse.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                buttonBrowseActionPerformed(evt);
            }
        });

        buttonManagePayments.setText("Manage payments");
        buttonManagePayments.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                buttonManagePaymentsActionPerformed(evt);
            }
        });

        buttonPrepareTaxReturn.setText("Prepare data for tax return");
        buttonPrepareTaxReturn.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                buttonPrepareTaxReturnActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jSeparator1)
                    .addGroup(layout.createSequentialGroup()
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                            .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)
                            .addGroup(layout.createSequentialGroup()
                                .addComponent(buttonNewInvoice)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                                .addComponent(buttonNewContact)
                                .addGap(18, 18, 18)
                                .addComponent(buttonEditInvoice)
                                .addGap(18, 18, 18)
                                .addComponent(buttonDeleteInvoice))
                            .addGroup(layout.createSequentialGroup()
                                .addComponent(labelFilter)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                                .addComponent(comboBoxFilter, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                                .addComponent(textFieldFilter, javax.swing.GroupLayout.PREFERRED_SIZE, 179, javax.swing.GroupLayout.PREFERRED_SIZE)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addComponent(buttonBrowse)))
                        .addGap(0, 0, Short.MAX_VALUE))
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(buttonManagePayments)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                        .addComponent(buttonPrepareTaxReturn)))
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 230, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(18, 18, 18)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(labelFilter)
                    .addComponent(comboBoxFilter, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(textFieldFilter, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(buttonBrowse))
                .addGap(18, 18, 18)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(buttonNewInvoice)
                    .addComponent(buttonNewContact)
                    .addComponent(buttonDeleteInvoice)
                    .addComponent(buttonEditInvoice))
                .addGap(26, 26, 26)
                .addComponent(jSeparator1, javax.swing.GroupLayout.PREFERRED_SIZE, 10, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(buttonManagePayments)
                    .addComponent(buttonPrepareTaxReturn))
                .addContainerGap())
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void buttonNewInvoiceActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonNewInvoiceActionPerformed
        InvoiceForm invoiceForm = new InvoiceForm(this);
        invoiceForm.setVisible(true);
    }//GEN-LAST:event_buttonNewInvoiceActionPerformed

    private void buttonEditInvoiceActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonEditInvoiceActionPerformed
        rowIndex = tableInvoices.getSelectedRow();
        if (rowIndex == -1) {
            JOptionPane.showMessageDialog(rootPane, "No invoice selected");
        } else {
            if (swingWorker != null) {
                throw new IllegalStateException("Operation in progress");
            }
            rowIndex = tableInvoices.getSelectedRow();
            Main_TableModel model = (Main_TableModel) tableInvoices.getModel();
            Integer invoiceNumber = (Integer) model.getValueAt(rowIndex, 0);
            swingWorker = new editSwingWorker(this, invoiceNumber, invoiceManager);
            swingWorker.execute();
        }
    }//GEN-LAST:event_buttonEditInvoiceActionPerformed

    private void buttonDeleteInvoiceActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonDeleteInvoiceActionPerformed
        rowIndex = tableInvoices.getSelectedRow();
        if (rowIndex == -1) {
            JOptionPane.showMessageDialog(rootPane, "No invoice selected");
        } else {
            int choice = JOptionPane.showConfirmDialog(rootPane, "Delete invoice?", null, JOptionPane.YES_NO_OPTION);
            if (choice == 0) {
                if (swingWorker != null) {
                    throw new IllegalStateException("Operation in progress");
                }
                swingWorker = new deleteSwingWorker(invoiceManager);
                swingWorker.execute();
            }
        }
    }//GEN-LAST:event_buttonDeleteInvoiceActionPerformed

    private void tableInvoicesMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_tableInvoicesMouseClicked
        if (rowIndex == tableInvoices.getSelectedRow()) {
            this.buttonEditInvoiceActionPerformed(null);
        } else {
            rowIndex = tableInvoices.getSelectedRow();
        }
    }//GEN-LAST:event_tableInvoicesMouseClicked

    private void buttonNewContactActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonNewContactActionPerformed
        ContactList contactList = null;
        ContactForm contactForm = new ContactForm(contactList);
        contactForm.setVisible(true);
    }//GEN-LAST:event_buttonNewContactActionPerformed

    private void comboBoxFilterActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_comboBoxFilterActionPerformed
        int index = comboBoxFilter.getSelectedIndex();
        switch (index) {
            case NONE:
                textFieldFilter.setText("");
                textFieldFilter.setEnabled(false);
                break;
            case NUMBER:
                textFieldFilter.setText("Enter invoice number");
                textFieldFilter.setEnabled(true);
                break;
            case VAR_SYMBOL:
                textFieldFilter.setText("Enter variable symbol");
                textFieldFilter.setEnabled(true);
                break;
            case DATE:
                textFieldFilter.setText("DD. MM. YYYY");
                textFieldFilter.setEnabled(true);
                break;
            case END_DATE:
                textFieldFilter.setText("DD. MM. YYYY");
                textFieldFilter.setEnabled(true);
                break;
            case CONTACT:
                textFieldFilter.setText("Click here to select contact");
                textFieldFilter.setEnabled(false);
                break;
        }
    }//GEN-LAST:event_comboBoxFilterActionPerformed

    private void textFieldFilterMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_textFieldFilterMouseClicked
        int index = comboBoxFilter.getSelectedIndex();
        if (index == CONTACT) {
            ContactList contactList = new ContactList(this);
            contactList.setVisible(true);
        }
    }//GEN-LAST:event_textFieldFilterMouseClicked

    private void buttonBrowseActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonBrowseActionPerformed
        buttonBrowse.setEnabled(false);
        int index = comboBoxFilter.getSelectedIndex();
        String content = textFieldFilter.getText();
        DateFormat dateParser = new SimpleDateFormat("dd. MM. yyyy");
        Invoice invoice = null;
        List<Invoice> invoicesFiltered = null;
        boolean oneInvoice = false;
        switch (index) {
            case NONE:
                try {
                    invoicesFiltered = invoiceManager.getAllInvoices();
                } catch (Exception ex) {
                    JOptionPane.showMessageDialog(rootPane, "Error while fetching invoices");
                }
                break;
            case NUMBER:
                int number = 0;
                try {
                    number = Integer.parseInt(content);
                } catch (NumberFormatException ex) {
                    JOptionPane.showMessageDialog(rootPane, "Enter a correct number");
                }
                if (number != 0) {
                    try {
                        invoice = invoiceManager.getInvoiceByNumber(number);
                        oneInvoice = true;
                    } catch (Exception ex) {
                        JOptionPane.showMessageDialog(rootPane, "Error while fetching invoices");
                    }
                }
                break;
            case VAR_SYMBOL:
                int varSymbol = 0;
                try {
                    varSymbol = Integer.parseInt(content);
                } catch (NumberFormatException ex) {
                    JOptionPane.showMessageDialog(rootPane, "Variable symbol must be a number");
                }
                if (varSymbol != 0) {
                    try {
                        invoice = invoiceManager.getInvoiceByVariableSymbol(varSymbol);
                        oneInvoice = true;
                    } catch (Exception ex) {
                        JOptionPane.showMessageDialog(rootPane, "Error while fetching invoices");
                    }
                }
                break;
            case DATE:
                Date date = null;
                try {
                    date = dateParser.parse(content);
                } catch (ParseException ex) {
                    JOptionPane.showMessageDialog(rootPane, "Enter a correct date (DD. MM. YYYY)");
                }
                if (date != null) {
                    try {
                        invoicesFiltered = invoiceManager.getInvoicesByDate(date);
                    } catch (Exception ex) {
                        JOptionPane.showMessageDialog(rootPane, "Error while fetching invoices");
                    }
                }
                break;
            case END_DATE:
                Date endDate = null;
                try {
                    endDate = dateParser.parse(content);
                } catch (ParseException ex) {
                    JOptionPane.showMessageDialog(rootPane, "Enter a correct date (DD. MM. YYYY)");
                }
                if (endDate != null) {
                    try {
                        invoicesFiltered = invoiceManager.getInvoicesByGetDate(endDate);
                    } catch (Exception ex) {
                        JOptionPane.showMessageDialog(rootPane, "Error while fetching invoices");
                    }
                }
                break;
            case CONTACT:
                if (contact == null) {
                    JOptionPane.showMessageDialog(rootPane, "Click in the text field to choose a contact");
                } else {
                    try {
                        invoicesFiltered = invoiceManager.getInvoicesByContact(contact);
                        contact = null;
                    } catch (Exception ex) {
                        JOptionPane.showMessageDialog(rootPane, "Error while fetching invoices");
                    }
                }
                break;
        }
        if (invoice != null) {
            InvoiceForm form = new InvoiceForm(this, invoice);
            form.setVisible(true);
        } else if (invoicesFiltered != null) {
            invoices = invoicesFiltered;
            tableInvoices.setModel(new Main_TableModel(invoices));
        } else if (oneInvoice) {
            JOptionPane.showMessageDialog(rootPane, "No invoice found");
        }
        buttonBrowse.setEnabled(true);
    }//GEN-LAST:event_buttonBrowseActionPerformed

    private void buttonManagePaymentsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonManagePaymentsActionPerformed
        java.awt.EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                new PaymentsList().setVisible(true);
            }
        });
    }//GEN-LAST:event_buttonManagePaymentsActionPerformed

    private void buttonPrepareTaxReturnActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonPrepareTaxReturnActionPerformed
        PaymentManager paymentManager = new PaymentManagerImpl();
        final int paymentSumTotal = paymentManager.getSumTotal();
        final int invoicesSumTotal = invoiceManager.getSumTotal();

        java.awt.EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                new TaxReturnForm(invoicesSumTotal, paymentSumTotal).setVisible(true);
            }
        });
    }//GEN-LAST:event_buttonPrepareTaxReturnActionPerformed

    public void refreshInvoices(Invoice invoice, int operation) {
        if (operation == REMOVE) {
            invoices.remove(invoice);
        } else if (operation == ADD) {
            invoices.add(invoice);
        } else if (operation == EDIT) {
            invoices.set(rowIndex, invoice);
        } else {
            throw new IllegalArgumentException("Wrong operation. Allowed operations are REMOVE (0), ADD (1), EDIT (2)");
        }
        tableInvoices.updateUI();
        rowIndex = -1;
    }

    public void setPaymentMethod(PaymentMethod method) {
        this.paymentMethod = method;
        this.textFieldFilter.setText(method.getName());
    }

    public void setContact(Contact contact) {
        this.contact = contact;
        this.textFieldFilter.setText(contact.getFirstName() + " " + contact.getSurname());
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        /*
         * Set the Nimbus look and feel
         */
        //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
        /*
         * If Nimbus (introduced in Java SE 6) is not available, stay with the
         * default look and feel. For details see
         * http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
         */
        try {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (ClassNotFoundException ex) {
            java.util.logging.Logger.getLogger(Main.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (InstantiationException ex) {
            java.util.logging.Logger.getLogger(Main.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            java.util.logging.Logger.getLogger(Main.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (javax.swing.UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(Main.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
        //</editor-fold>

        /*
         * Create and display the form
         */
        java.awt.EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                new Main().setVisible(true);
            }
        });


    }
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton buttonBrowse;
    private javax.swing.JButton buttonDeleteInvoice;
    private javax.swing.JButton buttonEditInvoice;
    private javax.swing.JButton buttonManagePayments;
    private javax.swing.JButton buttonNewContact;
    private javax.swing.JButton buttonNewInvoice;
    private javax.swing.JButton buttonPrepareTaxReturn;
    private javax.swing.JComboBox comboBoxFilter;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JSeparator jSeparator1;
    private javax.swing.JLabel labelFilter;
    public javax.swing.JTable tableInvoices;
    private javax.swing.JTextField textFieldFilter;
    // End of variables declaration//GEN-END:variables
}
